<?php
declare(strict_types=1);

namespace App\Wxc\Service;

use App\Wxc\Model\WxcShopInfo;
use App\Wxc\Service\Input\SharerMpListRecShopInput;
use App\Wxc\Service\Query\ShopInfoQuery;
use Deepwell\ChannelsShop\Api\Basic\Enums\ShopStatus;
use Hyperf\Redis\Redis;
use RedisException;

/**
 * 小程序首页内推客推荐服务
 */
class WxcSharerMpShopRecService
{
    /**
     * 有序集合存店铺ID，作为分页载体
     */
    protected string $zSetKeyForShopIds = 'wxc:sharerMp:rec:shopIds';

    /**
     * hash存店铺信息
     */
    protected string $hashKeyForShopInfo = 'wxc:sharerMp:rec:shopInfo';

    private Redis $redis;

    public function __construct()
    {
        $this->redis = redis();
    }

    public function generate(): void
    {
        $shopInfoService = container()->get(WxcShopInfoService::class);
        $getList = new ShopInfoQuery();
        $getList->status = ShopStatus::OpenFinished;
        $query = $shopInfoService->getQuery($getList);

        // 先删除
        $this->redis->del($this->zSetKeyForShopIds);
        $this->redis->del($this->hashKeyForShopInfo);

        $query->chunk(20, function ($items) use ($shopInfoService) {
            $shops = [];
            // 有序集合存店铺ID，作为分页载体
            // hash 存店铺信息
            /** @var WxcShopInfo $item */
            foreach ($items as $item) {
                $data = $shopInfoService->detail($item);
                $shops[] = $data;
            }
            // 开启事务
            $this->redis->multi();
            // 批量添加店铺ID到ZSET和店铺信息到HASH
            foreach ($shops as $shop) {
                $this->redis->zAdd($this->zSetKeyForShopIds, $shop['shop_id'], $shop['shop_id']); // 使用店铺ID为分数
                $this->redis->hSet($this->hashKeyForShopInfo, $shop['shop_id'], json_encode($shop)); // 使用JSON编码信息
            }
            // 执行事务
            $this->redis->exec();
        });
    }

    /**
     * 获取店铺列表
     * @param SharerMpListRecShopInput $input
     * @return array
     * @throws RedisException
     */
    public function getShopList(SharerMpListRecShopInput $input): array
    {
        $start = !empty($input->next_key) ? bcadd($input->next_key, '1') : '0';
        $shopIds = $this->redis->zRangeByScore($this->zSetKeyForShopIds, $start, PHP_INT_MAX, ['limit' => [0, $input->page_size]]);
        $shopInfos = $this->redis->hMGet($this->hashKeyForShopInfo, $shopIds);
        if (empty($shopInfos)) {
            return ['next_key' => '', 'shop_list' => [], 'has_more' => false];
        }

        $shopInfos = array_map(function ($shopInfo) {
            return json_decode($shopInfo, true);
        }, $shopInfos);
        // 确定是否还有更多
        $hasMore = count($shopIds) == $input->page_size;

        return ['next_key' => (string)end($shopIds), 'list' => array_values($shopInfos), 'has_more' => $hasMore];
    }
}